import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;

public class SIPparser {

	public String user;
	public String via;
	public String viaHost;
	public String viaBranch;
	public Integer contentLength;
	public String contact;
	public String callId;
	public String contentType;
	public String cSeq;
	public String from;
	public Integer fromPort;
	public InetAddress fromAddr;
	public String maxForwards;
	public String to;
	public InetAddress toAddr;
	public String userAgent;
	public String type; //type of data INVITE, etc
	String error;
	
	private HashMap<String, String> attribs;
	
	public SIPparser() {
		attribs = new HashMap<String, String>();
	}
	
	/*
	 * return errormsg
	 */
	public String parse(String data) {
		String[] lines = data.split("\\r?\\n");
		type = lines[0].trim(); //special case
		
		for(int i = 1; i < lines.length; ++i){ //start at 1 to ignore the first line that is handled separately
			parseLine(lines[i].trim());
		}
		
		setFields();
		
		return error;
	}
	
	public String parseLine(String line) {
		debug(line);
		String[] splittedLine = line.split(": ");
		if(splittedLine.length < 2){
			error("malformed line in SIP data, not following format k: value");
		}else{
			String key = splittedLine[0].trim();
			String value = splittedLine[1].trim();
			attribs.put(key, value);
		}
		return null;
	}
	
	private void setFields() {
		via = attribs.get("Via");
		
		viaHost = via.split(";")[0].split(" ")[1];
		viaBranch = via.split(";")[2]; //get the branch field from Via-field
		try{
			contentLength = Integer.parseInt(attribs.get("Content-Length"));
		}catch(NumberFormatException e){
			error(e.toString());
		}
		contact = attribs.get("Contact");
		callId = attribs.get("Call-ID");
		contentType = attribs.get("Content-Type");
		cSeq = attribs.get("CSeq");
		from = attribs.get("From");
		maxForwards = attribs.get("Max-Forwards");
		to = attribs.get("To");
		userAgent = attribs.get("User-Agent");
		if(!to.contains("@")){
			error("404");
		}
		user = to.split("@")[0].trim().split(":")[1].trim();
		
		//do some errorchecking
		if(callId == null){
			error("callId not present");
			return;
		}
		if(from == null){
			error("from not present");
			return;
		}
		if(to == null){
			error("to not present");
			return;
		}
		if(contentLength == null){
			error("contentLength not present");
			return;
		}
		
		//parse addresses
		String[] fromTmp = null;
		String toTmp = "";
		try{
			fromTmp = from.substring(from.indexOf('<')+1, from.indexOf('>')).split(":");
			toTmp = to.replace(user + "@", "");
			if(fromTmp.length < 2){
				error("We did not get valid from address");
				return;
			}
			toAddr = InetAddress.getByName(toTmp.substring(toTmp.indexOf('<')+1, toTmp.indexOf('>')).split(":")[1]);
			fromAddr = InetAddress.getByName(fromTmp[1]);
		}catch(UnknownHostException e){
			error(e);
			return;
		}
		
		//parse the from port if the standard sip port isn't used
		if(fromTmp.length > 2)
			fromPort = Integer.parseInt(fromTmp[2]);
		
	}
	
	public String toString() {
		return attribs.toString();
	}
	
	/*
	 * Print debugging information
	 */
	private void debug(Object msg) {
		//System.err.println("== DEBUG: " + msg.toString());
	}
	
	private void error(Object msg) {
		//System.err.println("== ERROR in SIPparser.java: " + msg.toString());
		this.error = msg.toString();
	}
	
	
}
